package com.wjjun.test.view

import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.SurfaceTexture
import android.os.Handler
import android.os.HandlerThread
import android.util.AttributeSet
import android.view.TextureView
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
import kotlin.math.min

/**
 * 律动动画
 */
open class LvDongTextureVIew : TextureView, TextureView.SurfaceTextureListener {

    var rowCount = 10

    var columnCount = 10

    val itemFrames = ArrayList<Int>()

    private lateinit var drawHandleThread: HandlerThread

    private lateinit var drawHandler: Handler

    private lateinit var drawRunnable: Runnable

    private lateinit var showHandleThread: HandlerThread

    private lateinit var showHandler: Handler

    private lateinit var showRunnable: Runnable

    private val frameQueue = LinkedBlockingQueue<Frame>(5)

    private val paint = Paint()

    private val radio = 15f


    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attr: AttributeSet) : super(context, attr) {
        init()
    }

    private fun init() {
        isOpaque = false
        initPaint()
        initThread()
        surfaceTextureListener = this
    }

    private fun initPaint() {
        paint.isAntiAlias = true
        paint.style = Paint.Style.FILL
    }

    private fun initThread() {
        drawHandleThread = HandlerThread("draw")
        showHandleThread = object : HandlerThread("show") {
            override fun run() {
                super.run()
            }
        }
    }

    /**
     * 初始化SurfaceTexture之后调用
     */
    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
        startDrawThread()
        startShowThread()
    }

    private fun startDrawThread() {
        if (!drawHandleThread.isAlive) {
            drawHandleThread.start()
        }
        if (!this::drawHandler.isInitialized) {
            drawHandler = Handler(drawHandleThread.looper)
        }
        drawHandler.removeCallbacksAndMessages(null)
        if (!this::drawRunnable.isInitialized) {
            val colors = arrayListOf(Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN)
            var index = 0
            drawRunnable = Runnable {
                val color = colors[(index++) % colors.size]
                frameQueue.put(Frame(color))

                drawHandler.postDelayed(drawRunnable, 100)
            }
        }
        drawHandler.post(drawRunnable)
    }


    private fun startShowThread() {
        if (!showHandleThread.isAlive) {
            showHandleThread.start()
        }
        if (!this::showHandler.isInitialized) {
            showHandler = Handler(showHandleThread.looper)
        }
        showHandler.removeCallbacksAndMessages(null)

        if (!this::showRunnable.isInitialized) {
            showRunnable = Runnable {
                try {
                    val frame = frameQueue.poll(1, TimeUnit.SECONDS)
                    drawFrame(frame)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
                showHandler.post(showRunnable)
            }
        }
        showHandler.post(showRunnable)
    }

    private fun drawFrame(frame: Frame) {
        val canvas = lockCanvas() ?: return
        val itemWidth = width.div(rowCount)
        val itemHeight = height.div(columnCount)
        for (i in 0..columnCount) {
            for (j in 0..rowCount) {
                var x = (itemWidth.times(j) + itemHeight.div(2)).toFloat()
                var y = (itemHeight.times(i) + itemHeight.div(2)).toFloat()
                paint.color = frame.color
                paint.setShadowLayer(10f, 0f, 0f, frame.color)
                canvas.drawCircle(x, y, min(radio, itemHeight.div(2).toFloat()), paint)
            }
        }
        unlockCanvasAndPost(canvas)
    }


    override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
    }

    override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

    }

    override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {

        return true
    }


}